package org.example.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.example.config.ApiConfig;
import org.example.util.HttpClientUtil;
import org.example.util.constantUtil.ConstantUtil;
import org.example.util.DeviceUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;

@Component
@Data
@Slf4j
public class DeviceService {
    @Autowired
    private ApiConfig apiConfig;

    private final Integer PAGE_SIZE=1000;
    private LocalDateTime lastRefreshTime=LocalDateTime.MIN;

    /**
     * 项目启动时启动，获取设备列表，建立映射表
     */
    @PostConstruct
    public boolean init() {
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date(System.currentTimeMillis());
        System.out.println(formatter.format(date));
        log.info(formatter.format(date)," Device list generating...");
        String token= HttpClientUtil.get_token(apiConfig.getTokenApi(), apiConfig.getUsername(), apiConfig.getPassword())[0];
        return getDevice(token);
    }

    public String getUUIDByImei(String imei){
        String uuid= DeviceUtil.SNtoUUID.get(imei);
        long minutesSinceLastRefresh = getLastRefreshDuration();
        if(uuid==null && minutesSinceLastRefresh>=5){
            log.info("out of 5 min, refresh!");
            this.refreshDevice(apiConfig.getUsername(), apiConfig.getPassword());
            uuid=DeviceUtil.SNtoUUID.get(imei);// 重新获取uuid
        }
        return uuid;
    }
    public boolean refreshDevice(String username,String password){
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date(System.currentTimeMillis());
        System.out.println(formatter.format(date));
        log.info(formatter.format(date), "Device list refreshing...");
        String token=HttpClientUtil.get_token(apiConfig.getTokenApi(),username,password)[0];
        // 更新最后一次刷新的时间
        lastRefreshTime = LocalDateTime.now();
        return getDevice(token);
    }

    private long getLastRefreshDuration(){
        LocalDateTime now = LocalDateTime.now();
        Duration duration = Duration.between(lastRefreshTime, now);
        long minutesSinceLastRefresh = duration.toMinutes();
        log.info("lastRefreshTime:{} now:{}",lastRefreshTime,now);
        return minutesSinceLastRefresh;
    }
    private boolean getDevice(String token){
        //应该还要判断无法获取到设备列表怎么办
        log.info("Getting Device...");
        int page=0;
        String url= apiConfig.getDeviceInfosApi() +"?"+"pageSize="+PAGE_SIZE+"&"+"page="+ page +"&"+"type="+ ConstantUtil.TYPE;
        String[] resultStr=HttpClientUtil.get_data(url,token);//String 格式获取结果, [0]为statusCode，[1]为结果(结果可能不是json)
        boolean flag=false;
        if(resultStr==null){
            return false;
        }
        if(Integer.parseInt(resultStr[0])!=200){//没有正确拿到信息
            log.error("GetDeviceERROR: code:"+resultStr[0]+" result:"+resultStr[1]);
            try{//错误但是返回json格式
                //尝试拿数据
                JSONObject jsonResult = JSONObject.parseObject(resultStr[1]);
                log.info(jsonResult.toString());
                String msg=jsonResult.get("message").toString();
                log.error(msg);
                return false;
            } catch (Exception e){//错误而且返回的不是JSON格式
                log.error("msg: "+resultStr[1]);
                return false;
            }

        }
        int totalPages=0;
        while(Integer.parseInt(resultStr[0])==200){
            System.out.println("page"+page);
            totalPages++;
            //获取设备列表
            JSONObject jsonResult = JSONObject.parseObject(resultStr[1]);
            JSONArray dataList=jsonResult.getJSONArray("data");
            //遍历提取id和name存到map里
            log.info("Device num:"+dataList.size());
            for(int i=0;i<dataList.size();i++){
                System.out.println("imei:"+dataList.getJSONObject(i).get("name").toString());
                DeviceUtil.SNtoUUID.put(dataList.getJSONObject(i).get("name").toString(),
                        dataList.getJSONObject(i).getJSONObject("id").get("id").toString());
                // 获取设备创建时间
                DeviceUtil.ImeiCreatedTime.put(dataList.getJSONObject(i).get("name").toString(),
                        Long.parseLong(dataList.getJSONObject(i).get("createdTime").toString()));
                // 客户列表都需要进行刷新(因为可能会发生改变)
                // 获取设备项目号
                Object customerTitle=dataList.getJSONObject(i).get("customerTitle");
                if(customerTitle!=null){  // 非空时
                    // 添加到imei和customerTitle映射表
                    DeviceUtil.ImeiCustomerTitle.put(dataList.getJSONObject(i).get("name").toString(),
                            dataList.getJSONObject(i).get("customerTitle").toString());
                    // 添加到uuid和customerTitle映射表
                    DeviceUtil.uuidCustomerTitle.put(dataList.getJSONObject(i).getJSONObject("id").get("id").toString(),
                            dataList.getJSONObject(i).get("customerTitle").toString());
                    // 添加到客户列表(非空)
                    if(!DeviceUtil.customerTitleList.contains(dataList.getJSONObject(i).get("customerTitle").toString())){
                        DeviceUtil.customerTitleList.add(dataList.getJSONObject(i).get("customerTitle").toString());
                    }
                    // 添加到customerTitle和设备列表映射表
                    if(!DeviceUtil.customerTitleDeviceList.containsKey(customerTitle.toString())){  // 原来不含则新建
                        DeviceUtil.customerTitleDeviceList.put(customerTitle.toString(),new ArrayList<>());
                    }
                    DeviceUtil.customerTitleDeviceList.get(customerTitle.toString()).add(dataList.getJSONObject(i).get("name").toString());
                } else{  // customerTitle为null时
                    // 添加到imei和customerTitle映射表
                    DeviceUtil.ImeiCustomerTitle.put(dataList.getJSONObject(i).get("name").toString(), null);
                    // 添加到uuid和customerTitle映射表
                    DeviceUtil.uuidCustomerTitle.put(dataList.getJSONObject(i).getJSONObject("id").get("id").toString(), null);
                }

            }
            //判断是否有还有下一页
            if(!Boolean.parseBoolean(jsonResult.get("hasNext").toString())){//最后一页
                System.out.println("最后一页啦，page:"+page+" totalPages:"+totalPages);
                flag=true;//查询成功
                break;
            }
            page++;//下一页继续
            url= apiConfig.getDeviceInfosApi()+"?"+"pageSize="+PAGE_SIZE+"&"+"page="+String.valueOf(page)+"&"+"type="+ConstantUtil.TYPE;
//            url="http://47.92.164.101:8080/api/tenant/deviceInfos?pageSize=100&page="+String.valueOf(page)+"&type=电池包";
            resultStr=HttpClientUtil.get_data(url,token);//String 格式获取结果, [0]为statusCode，[1]为结果(结果可能不是json)
            if(resultStr==null){
                log.error("Cannot get deviceInfo, resultStr null! url:"+url);
                break;
            }
        }

        // 打印设备数量信息
//        displayDeviceInfo();
        log.info("deviceNum:"+DeviceUtil.SNtoUUID.size());
        log.info("customerNum:"+DeviceUtil.customerTitleList.size());
        displayCustomerInfo();

        return flag;
    }
    private void displayCustomerInfo(){
        for(int i=0;i<DeviceUtil.customerTitleList.size();i++){
            System.out.println(DeviceUtil.customerTitleList.get(i));
        }
    }

    /**
     * 这里是每天0:05执行一次，更新设备映射表，05分执行保证在Token刷新之后
     * @return
     */
    @Scheduled(cron = "0 5 0 1/1 * ? ")
//    @Scheduled(cron = "0/10 * * * * ?")
    public void start() {
        init();
    }
}
